<template>
  <a-form-model
    :model="formValue"
    ref="form"
    :rules="formRules"
    size="small"
    :class="{ 'search-model': mode === 'search', 'edit-model': ['edit', 'add'].includes(mode)}"
    v-bind="customFormAttr"
  >
    <div class="form-col" v-for="column, index in formColumns" :key="index">
      <a-form-model-item
        :label="item.title"
        v-for="item in column"
        :key="item.key"
        :prop="item.key"
        :colon="item.colon"
        :class="`form_item_${item.key}`"
      >
        <!-- 自定义插槽 -->
        <template v-if="item.form.slot">
          <slot :name="item.form.slot" :params="formValue" :column="item"></slot>
        </template>

        <!-- 搜索模式下范围搜索 -->
        <template v-else-if="mode === 'search' && item.form.querySection">
          <a-input-group compact>
            <a-input v-model="formValue[item.key + '_min']" placeholder="起始值" style="width: 70px" />
            <span class="query-section-driver">-</span>
            <a-input v-model="formValue[item.key + '_max']" placeholder="结束值" style="width: 70px" />
          </a-input-group>
        </template>

        <!-- 组件渲染 -->
        <component
          v-else
          :is="getComponentsName(item.form)"
          v-model="formValue[item.key]"
          v-bind="formatAttrs(item.form)"
          :keyName="item.key"
          v-on="item.form.handler"
          :disabled="getDisabledStatus(item.form)"
          class="item-class"
          :style="(isSearch && getComponentsName(item.form) === 'a-input') ? { width: `${(item.form.placeholder.length || 0) * 18}px` } : {}" 
        >
          <!-- 下拉选择框 -->
          <template v-if="getComponentsName(item.form) === 'a-select' && item.form.dict">
            <a-select-option
              v-for="dict in item.form.dict"
              :value="dict.value"
              :key="dict.value"
            >{{ dict.label }}{{dict.remark ? ' ('+ dict.remark +') ' : ''}}</a-select-option>
          </template>
          <!-- 复选框 -->
          <template v-if="getComponentsName(item.form) === 'a-checkbox-group' && item.form.dict">
            <a-checkbox
              v-for="dict in item.form.dict"
              :value="dict.value"
              :key="dict.value"
            >{{ dict.label }}</a-checkbox>
          </template> 
          <!-- 单选框 -->
          <template v-if="getComponentsName(item.form) === 'a-radio-group' && item.form.dict">
            <a-radio
              v-for="dict in item.form.dict"
              :value="dict.value"
              :key="dict.value"
            >{{ dict.label }}</a-radio>
          </template>
        </component>

        <!-- 非搜索模式下 -->
        <a-alert
          v-if="mode !== 'search' && item.form.tips"
          :message="item.form.tips"
          banner
        ></a-alert>
      </a-form-model-item>

      <a-form-model-item>
        <!-- 默认插槽 -->
        <slot></slot>
      </a-form-model-item>
    </div>
    
  </a-form-model>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import { FormModel } from 'ant-design-vue'
import Upload from '@/components/src/Upload'
import { isEqual, cloneDeep } from 'lodash-es'

@Component({
  components: {
    Upload
  }
})
export default class CustomForm extends Vue {
  @Prop({
    type: Array,
    default: () => []
  })
  public FormList!: []
  // 当前表单默认值
  @Prop({
    type: Object,
    default() {
      return {}
    }
  })
  public value!: object
  // 操作 add | edit
  @Prop({ type: String, default: '' }) public mode!: string

  // 列数
  @Prop({ type: Number, default: 1 }) public cols!: number


  public formValue: {
    [propName: string]: any
  } = {}

  public $refs: any

  // 格式化后表单column
  public formatedFormList: ITable.IColumn[] = []

  // 表单元素布局
  public formItemLayout = {
    // labelCol: {span: 6},
    // wrapperCol: {span: 18}
  }

  get isSearch() {
    return this.mode === 'search'
  }

  // 表单属性
  get customFormAttr() {
    return Object.assign({}, this.formItemLayout, this.$attrs)
  }

  // 多列表格数据
  get formColumns() {
    if (this.mode === 'search') {
      return [this.formatFormList]
    }
    let arr: ITable.IColumn[][] = []
    this.formatFormList.forEach(item => {
      const currentIndex = item.form?.col || 0
      if (!arr[currentIndex]) {
        arr[currentIndex] = []
      }
      arr[currentIndex].push(item)
    })
    return arr
  }

  // 处理不同mode表单渲染问题
  get formatFormList() {
    return this.mode === 'search' ?
      this.FormList.map((column: ITable.IColumn) => {
        const tempColumn = cloneDeep(column)
        // 搜索模式下添加字段全部字段
        if (tempColumn.form && tempColumn.form.dict && tempColumn.form.dict.length) {
          // 可控制搜索字段是否需要全部((true | 默认添加全部) && 未包含全部的时候)
          if (
            (
              typeof tempColumn.form.isShowAll === 'undefined'
              || (typeof tempColumn.form.isShowAll !== 'undefined' && tempColumn.form.isShowAll)
            )
            && !tempColumn.form.dict.find(item => item.label === '全部')) {
            tempColumn.form.dict.unshift({
              label: '全部',
              value: ''
            })
          }
        }
        return tempColumn;
      }) : this.FormList.filter((column: ITable.IColumn) => {
        return (
          (column.form && !column.form.renderMode) ||
          (column.form &&
            column.form.renderMode &&
            column.form.renderMode.includes(this.mode))
        )
      })
  }

  // 获取表单验证
  get formRules() {
    // 搜索模式
    if (this.mode === 'search') {
      return {}
    }
    let rules: Record<string, any[]> = {}
    this.formatFormList.forEach(item => {
      const validate = item?.form?.validate
      if (validate) {
        // 快捷校验方式别名
        if (typeof validate === 'string') {
          rules[item.key] = this.getValidate(item)
        } else {
          rules[item.key] = validate
        }
      }
    })
    return rules
  }

  // 获取需要转换string和array的字段
  get stringToArrayFiled() {
    return this.FormList.filter((column: ITable.IColumn) => {
      return column.form && column.form.stringToArray
    }).map((column: ITable.IColumn) => column.key)
  }

  public moutend() {
    // this.initForm()
    // this.formatFormList()
  }

  public getValidate(item: ITable.IColumn) {
    const validate = item?.form?.validate;
    let rules: any[] = []
    switch (validate) {
      case '*': 
        rules = [
          { required: true, message: item?.form?.placeholder, trigger: 'change' }
        ];
        break;
    }
    return rules;
  }

  @Watch('value', { deep: true, immediate: true })
  public handleValueChange() {
    // 数据未修改时则不更新
    // console.log('value-change =>', JSON.stringify(this.value))
    if (!isEqual(this.formValue, this.value)) {
      this.formValue = this.stringToArray(Object.assign({}, this.formValue, this.value))
    }
  }

  @Watch('formValue', { deep: true })
  public handleFormChange(newValue: any, oldValue: any) {
    console.log('formValue-change =>', JSON.stringify(this.formValue), newValue, oldValue)
    this.$emit('input', this.formValue)
  }

  public stringToArray(data: any, toArray: boolean = true) {
    let obj: any = Object.assign({}, data)
    Object.keys(obj).forEach((key: string) => {
      if (this.stringToArrayFiled.includes(key)) {
        // 针对tree组件checkStrictly独立判断
        if (obj[key] && obj[key].checked) {
          if (toArray) {
            obj[key].checked = obj[key].split(',')
          } else {
            obj[key] = obj[key].checked.join(',')
          }
        } else {
          /**
           * @description 修复空字符串转数组后数据长度不为0问题
           * @author wucheshi
           * @time 2021-11-27
          */
          obj[key] = toArray ? (obj[key] ? obj[key].split(',') : []) : obj[key].join(',')
        }
      }
    })
    return obj
  }

  // @Watch('mode')
  // public handleModeChange() {
  //   this.initForm()
  // }

  // 初始化表单数据
  public initForm() {
    this.FormList.forEach((item: ITable.IColumn) => {
      this.$set(this.formValue, item.key, item.form ? item.form.defaultValue : '')
      // 设置默认值
      this.$refs.form.setFieldsValue({
        [item.key]: item.form ? item.form.defaultValue : ''
      })
    })
  }

  public formatAttrs(attrs: ITable.IForm) {
    if (this.mode === 'search') {
      attrs.placeholder = '-'
    }
    return attrs
  }

  // 禁用状态特殊处理
  public getDisabledStatus(form: ITable.IForm) {
    if (form.customDisabled) {
      return (form.customDisabled as any)(this.formValue, form)
    }
    // 添加预览模式 仅仅能查看不能编辑
    if (this.mode === 'preview') return true
    // 可以指定模式控制
    if (Array.isArray(form.disabled)) {
      return form.disabled.includes(this.mode)
    }
    return form.disabled || false
  }

  // 格式化组件名称
  public getComponentsName(form: ITable.IForm) {
    return form.typeAlias || form.type
  }

  // 提交数据
  public submit() {
    return new Promise((resolve, reject) => {
      ;(this.$refs.form as any).validate((valid: boolean, err: object) => {
        if (valid) {
          console.log('submit => ', this.formValue)
          resolve(this.stringToArray(this.formValue, false))
        } else {
          reject(err)
        }
      })
    })
  }

  // 重置
  public resetFields() {
    // for (let i in this.form) {
    //   if (this.form[i]) {
    //     this.form[i] = ''
    //   }
    // }
    // @todo 处理编辑是额外字段到添加时覆盖commonParams提交问题
    this.formValue = {}
    this.formatFormList.forEach((column: ITable.IColumn) => {
      this.formValue[column.key] = ''
    })
    this.formValue = this.stringToArray(Object.assign({}, this.formValue))
    this.$nextTick(() => {
      this.$refs.form.resetFields()
    })
  }

  // 自动收集表单验证数据
  public autoCollectValite() {
    // let rules: any = {}
    // this.FormList.forEach((item: any) => {
    //   const arr = item.form.validate.split(',')
    //   rules[item.key] = arr.map((key: string) => this.rules[key])
    // })
  }
}
</script>

<style lang="less" scoped>
.item-class {
  width: 100%;
  min-width: 120px;
}
.query-section-driver {
  display: inline-block;
  height: 100%;
  padding: 5px;
}
.search-model {
  /deep/ .ant-input {
    padding: 4px 6px;
    height: 28px;
  }
}
.edit-model {
  display: flex;
  /deep/ .ant-form-item {
    margin-bottom: 0!important;
  }
  /deep/ .form-col {
    flex: 1;
    min-width: 400px;
  }
}

</style>
